﻿using System;
using System.Collections.Generic;
using System.Hyper.Cache;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Microsoft.Practices.Unity;
using Wyn.PMS.Common.Utils;
using Wyn.PMS.Entity.Entities;
using Wyn.PMS.Entity.IDataAccess;

namespace Wyn.PMS.Common.NightAudit
{
    public static class BizCodeCache
    {
        public const string KEY = "BizCodeCache";

        public static DateTime LastDateTime { get; set; }

        private static readonly IUnityContainer container = UnityContainerService.GetContainer();

        public static void CacheBizCode()
        {
            IDictKeyValueRepository keyValueRepository = container.Resolve<IDictKeyValueRepository>();

            IList<DictKeyValue> bizCodes = null;

            var transactionOptions = new System.Transactions.TransactionOptions();

            transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;

            try
            {
             
                using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions))
                {
                    bizCodes = keyValueRepository.BatchFind(GlobalConst.ROOT_HOTEL_ID, k => k.IsValid == true);

                    scope.Complete();
                }
               
                if (bizCodes != null && bizCodes.Any())
                {
                    var hotels = bizCodes.Select(k => k.HotelID).Distinct();

                    foreach (var hotel in hotels)
                    {
                        CacheHotelCode(hotel, bizCodes.Where(k => k.HotelID == hotel));
                    }
                }
            }
            catch (Exception ex)
            {
                Wyn.PMS.Common.SecurityControl.OperateLog.ErrorLog(ex.Message, ex);
            }

            LastDateTime = DateTime.Now;
        }

        public static IEnumerable<DictKeyValue> GetBizCode(string hotelId)
        {
            ICacheProvider cacheProvider = CacheProvider.GetInstance();

            var bucket = cacheProvider.Get<KeyValueBucket>(KEY + hotelId);

            if(bucket!=null)return bucket.Codes;

            return null;
        }

        public static IEnumerable<DictKeyValue> GetBizCode(string hotelId, string parentKey)
        {
            ICacheProvider cacheProvider = CacheProvider.GetInstance();

            var bucket = cacheProvider.Get<KeyValueBucket>(KEY + hotelId);

            if (bucket == null || bucket.Codes == null || !bucket.Codes.Any())
            {
                CacheBizCode();
            }

            if (bucket != null && bucket.Codes != null && bucket.Codes.Any())
            {
                return bucket.Codes.Where(k => k.Keys == parentKey && k.IsValid).ToList();
            }

            return null;
        }

        public static DictKeyValue GetKeyName(string hotelId, string parentKey, string keyValue)
        {
            ICacheProvider cacheProvider = CacheProvider.GetInstance();

            var bucket = cacheProvider.Get<KeyValueBucket>(KEY + hotelId);

            if (bucket != null && bucket.Codes != null && bucket.Codes.Any())
            {
                return bucket.Codes.FirstOrDefault(k => k.Keys == parentKey && k.KeyValue == keyValue);
            }

            return null;
        }

        public static DictKeyValue GetKeyValue(string hotelId, string parentKey, string keyName)
        {
            ICacheProvider cacheProvider = CacheProvider.GetInstance();

            var bucket = cacheProvider.Get<KeyValueBucket>(KEY + hotelId);

            if (bucket != null && bucket.Codes != null && bucket.Codes.Any())
            {
                return bucket.Codes.FirstOrDefault(k => k.Keys == parentKey && k.KeyName == keyName);
            }

            return null;
        }

        public static bool IsAliveBizCode(string hotelId)
        {
            ICacheProvider cacheProvider = CacheProvider.GetInstance();

            return cacheProvider.MyCache.Contains(KEY + hotelId);
        }
        
        private static void CacheHotelCode(string hotel, IEnumerable<DictKeyValue> codes)
        {
            ICacheProvider cacheProvider = CacheProvider.GetInstance();

            KeyValueBucket bucket = new KeyValueBucket();

            bucket.HotelId = hotel;

            bucket.LastModifiedTime = DateTime.Now;

            bucket.Codes = codes.ToList();

            var key = KEY + hotel;
            
            if (cacheProvider.MyCache.Contains(key))
            {
                cacheProvider.Remove(key);
            }

            cacheProvider.Insert(key, bucket);
        }

    }

    [Serializable]
    [DataContract]
    public class KeyValueBucket
    {
        [DataMember]
        public string HotelId { get; set; }

        [DataMember]
        public IList<DictKeyValue> Codes { get; set; }

        [DataMember]
        public DateTime LastModifiedTime { get; set; }

    }
}
